package org.one.stone.soup.grfxML.plugin.builder;

import java.util.Vector;

import org.one.stone.soup.grfxML.DataChildren;
import org.one.stone.soup.grfxML.DataMouse;
import org.one.stone.soup.grfxML.DataNode;
import org.one.stone.soup.grfxML.DataPoint;
import org.one.stone.soup.grfxML.DataPoints;
import org.one.stone.soup.grfxML.DataState;
import org.one.stone.soup.grfxML.GrfxMLEngine;
import org.one.stone.soup.grfxML.GrfxMLProcessor;
import org.one.stone.soup.grfxML.plugin.SimplePlugin;
import org.one.stone.soup.grfxML.plugin.grfxMLCaster;
import org.one.stone.soup.mjdb.data.field.DataLinker;
import org.one.stone.soup.mjdb.data.field.Field;

public class PolygonEditor extends SimplePlugin {

	private static final int ARG_EDIT = 0;
	private static final int ARG_POINTS = 1;
	private static final int ARG_SPLINE_POINTS = 2;

	private DataNode node;

	private boolean isSpline;
	private boolean processing = false;

	private DataState edit = new DataState();

	private DataPoints polyPoints;
	private DataPoints polySplinePoints;
	private DataMouse mouse;
	private DataPoints originalPolySplinePoints;

	private Vector points;
	private Vector splinePoints;
/**
 * NodeBuilder constructor comment.
 */
public PolygonEditor(GrfxMLEngine engine){
	super(engine);

	polyPoints = new DataPoints();
	polySplinePoints = new DataPoints();

	originalPolySplinePoints = polySplinePoints;
}
/**
 * initialize method comment.
 */
public void initialize()
{
	node = parent.getParent();
	mouse = getEngine().getAPI().getMouse();
	points = new Vector();

	if(polySplinePoints==originalPolySplinePoints)
	{
		isSpline=false;
	}
	else
	{
		isSpline=true;
		splinePoints=new Vector();
	}

	int x=0;
	int y=0;

	addPoint(x,y,-1);
	addPoint(x+10,y+10,-1);

	getEngine().getAPI().commit();
}
/**
 * process method comment.
 */
public void process()
{
	if(processing==true)
		return;

	if(edit.getValue()==false)
	{
		return;
	}

	try{
		processing=true;

		if(mouse.getButton2Pressed().getValue()==true)
		{
			if(isSpline)
			{
				for(int loop=0;loop<splinePoints.size();loop++)
				{
					DataNode testNode = (DataNode)splinePoints.elementAt(loop);
					if(testNode.getBehaviour().getOver().getValue()==true)
					{
						processing=false;
						return;
					}
				}
			}

			int x=mouse.getPosition().getValueX();
			int y=mouse.getPosition().getValueY();

			x = x-node.getTranslation().getPositionView().getValueX();
			y = y-node.getTranslation().getPositionView().getValueY();

			int index = -1;
			for(int loop=0;loop<points.size();loop++)
			{
				DataNode testNode = (DataNode)points.elementAt(loop);
				if(testNode.getBehaviour().getOver().getValue()==true)
				{
					index = loop;
				}
			}

			if(index!=-1 && mouse.getButton2DoubleClicked().getValue()==false)
			{
				processing = false;
				return;
			}

			addPoint(x,y,index);

		//	append.setValue(false,this);
		}

		if(mouse.getButton1Pressed().getValue()==true && mouse.getButton1DoubleClicked().getValue()==true)
		{
			int x=mouse.getPosition().getValueX();
			int y=mouse.getPosition().getValueY();

			x = x-node.getTranslation().getPositionView().getValueX();
			y = y-node.getTranslation().getPositionView().getValueY();

			DataNode foundNode = null;

			for(int loop=0;loop<points.size();loop++)
			{
				DataNode testNode = (DataNode)points.elementAt(loop);
				if(testNode.getBehaviour().getOver().getValue()==true)
				{
					foundNode = testNode;

					node.getChildren().remove(foundNode,this);

					points.remove(foundNode);
					polyPoints.remove(foundNode.getTranslation().getPosition(),this);

					if(isSpline)
					{
						if(isSpline)
						{
							splinePoints.remove(loop);
						}
						polySplinePoints.remove(loop,this);
					}
				}
			}

			if(foundNode!=null)
			{
				getEngine().getAPI().commit();
			}

		}
	}
	catch(Exception e){e.printStackTrace();}

	processing = false;
}
/**
 * register method comment.
 */
public void register(DataLinker store)
{
	polyPoints = grfxMLCaster.cast(polyPoints,getArg(polyPoints,ARG_POINTS,store));
	polySplinePoints = grfxMLCaster.cast(polySplinePoints,getArg(polySplinePoints,ARG_SPLINE_POINTS,store));
	edit = grfxMLCaster.cast(edit,getArg(edit,ARG_EDIT,store));
}
/**
 * replace method comment.
 */
public void replace(Field oldObj, Field newObj)
{
	polyPoints = grfxMLCaster.replace(polyPoints,oldObj,newObj);
	polySplinePoints = grfxMLCaster.replace(polySplinePoints,oldObj,newObj);
	edit = grfxMLCaster.replace(edit,oldObj,newObj);
}
/**
 * stop method comment.
 */
public void stop() {}

public void addPoint(int x,int y,int index)
{
	try{
		DataNode dragger = createDragger(node.getChildren(),getPath()+"."+polyPoints.size(),x,y);
		DataPoint point = dragger.getTranslation().getPosition();

		if(index==-1)
		{
			polyPoints.add(point,this);
			points.addElement(dragger);
		}
		else
		{
			polyPoints.insert(point,index,this);
			points.insertElementAt(dragger,index);
		}

		if(isSpline)
		{
			if(polyPoints.size()==1)
			{
				dragger = createDragger(node.getChildren(),getPath()+".splinePoint."+polyPoints.size(),x+10,y);
				point = dragger.getTranslation().getPosition();

				polySplinePoints.add(point,this);
				splinePoints.addElement(dragger);
			}
			else if(polyPoints.size()==2)
			{
				dragger = createDragger(node.getChildren(),getPath()+".splinePoint."+polyPoints.size(),x,y+10);
				point = dragger.getTranslation().getPosition();

				polySplinePoints.add(point,this);
				splinePoints.addElement(dragger);
			}
			else
			{
				DataPoint p = null;
				if(index==-1 || index==0)
				{
					p = polyPoints.get(polyPoints.size()-2);
				}
				else
				{
					p = polyPoints.get( index-2 );
				}
				DataPoint splinePoint = new DataPoint();
				GrfxMLProcessor.middle(new DataPoint(x,y),p,splinePoint);

				dragger = createDragger(node.getChildren(),getPath()+".splinePoint."+polyPoints.size(),splinePoint.getValueX(),splinePoint.getValueY());
				point = dragger.getTranslation().getPosition();

				if(index==-1)
				{
					polySplinePoints.add(point,this);
					splinePoints.addElement(dragger);
				}
				else
				{
					polySplinePoints.insert(point,index,this);
					splinePoints.insertElementAt(dragger,index);
				}
			}
		}

		getEngine().getAPI().commit();
	}
	catch(Exception e)
	{
		e.printStackTrace();
	}
}

public DataNode createDragger(DataChildren target,String id,int x,int y)
{
	StringBuffer template = new StringBuffer("<node id=\"dragger\">");
	template.append("<translation><position id=\"position\" x=\""+x+"\" y=\""+y+"\"/></translation>");
	template.append("<behaviour><selectable state=\"true\"/><draggable state=\"true\"/><over id=\"over\"/></behaviour>");
	template.append("<shape><circle><radius size=\"10\"/><color alpha=\"0\"/></circle></shape>");
	template.append("<children><node><translation><visible id=\"over\"/></translation>");
	template.append("<shape><circle><radius size=\"10\"/><color alpha=\"50\"/></circle><circle><radius size=\"10\"/><color alpha=\"70\"/><filled state=\"false\"/></circle></shape>");
	template.append("</node></children></node>");

	return getEngine().getAPI().buildPrototype(template.toString(),id,x,y,target,true);
}

}